package de.hypoport.einarbeitung.scrumspirit.helper;

import java.util.Locale;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import org.apache.wicket.util.tester.ITestPageSource;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.rules.ExternalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * Diese Klasse baut die nötigen Resourcen auf, die für das Testen einer Wicket page nötig sind
 * 
 * @see http://paulszulc.wordpress.com/2009/08/17/wickettestbase-base-class-for-testing-wicket-spring-web-applications/
 * 
 */
public class WicketTestPageResource<T extends Page> extends ExternalResource {



	protected WicketTester tester;

	private Page testingPage;
	private final MyWebApplication myWebApplication;

	public WicketTester getTester() {
		return tester;
	}

	public void setTester(WicketTester tester) {
		this.tester = tester;
	}

	public Page getTesingPage() {
		return testingPage;
	}

	public void setTesingPage(Page testingPage) {

		this.testingPage = testingPage;
	}

	public WicketTestPageResource(Class<? extends Page> pageClass) {

		myWebApplication = new MyWebApplication();

		tester = new WicketTester(myWebApplication);
		tester.setupRequestAndResponse();
		tester.getWicketSession().setLocale(getLocale());
		tester.getApplication().addComponentInstantiationListener(
				new SpringComponentInjector(tester.getApplication(), myWebApplication.getApplicationContext(), false));

		//		tester = new WicketTester(myWebApplication);
		try {
			this.testingPage = pageClass.newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	protected void before() throws Throwable {

		//start and render the test page
		tester.startPage(new ITestPageSource() {

			private static final long serialVersionUID = 1L;

			@Override
			public Page getTestPage() {
				return testingPage;
			}
		});

	};

	@Override
	protected void after() {
		tester.destroy();
	}

	/**
	 * Override to change locale
	 * 
	 * @return locale, default EN
	 */
	protected Locale getLocale() {
		return new Locale("DE");
	}

	public void assertRenderedPage() {
		tester.assertRenderedPage(this.testingPage.getClass());

	};


	@ContextConfiguration(locations = {"classpath:/testApplicationContext.xml"})
	public class MyWebApplication extends WebApplication {

		@Autowired
		private ApplicationContext applicationContext;

		@SpringBean
		private EntityManagerFactory entityManagerFactory;

		@SpringBean
		private EntityManager entityManager;

		@SpringBean
		private PlatformTransactionManager transactionManager;

		@Override
		protected void init() {

			//		tester = new WicketTester((WebApplication) applicationContext.getBean("wicketApplication"));
			if (null == applicationContext) {
				applicationContext = createContext();
			}

			SpringComponentInjector listener = new SpringComponentInjector(this, applicationContext, false);
			this.addComponentInstantiationListener(listener);

			if (null == entityManagerFactory) {
				entityManagerFactory = Persistence.createEntityManagerFactory("eclipseLinkFile");
			}

			if (null == entityManager) {
				entityManager = entityManagerFactory.createEntityManager();
			}

			if (null == transactionManager) {
				transactionManager = new JpaTransactionManager(this.entityManagerFactory);
			}

		}

		public ApplicationContext getApplicationContext() {
			return applicationContext;
		}

		@Override
		public Class<? extends Page> getHomePage() {
			return testingPage.getPageClass();
		}

		public EntityManagerFactory getEntityManagerFactory() {
			return entityManagerFactory;
		}

		public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
			this.entityManagerFactory = entityManagerFactory;
		}

		public EntityManager getEntityManager() {
			return entityManager;
		}

		public void setEntityManager(EntityManager entityManager) {
			this.entityManager = entityManager;
		}

		public PlatformTransactionManager getTransactionManager() {
			return transactionManager;
		}

		public void setTransactionManager(PlatformTransactionManager transactionManager) {
			this.transactionManager = transactionManager;
		}

		protected ApplicationContext createContext() {
			return new ClassPathXmlApplicationContext("classpath:/testApplicationContext.xml");
		}

	} // ende MyWebApplication class
} // ende WicketTestPageResource class

